package impl

import (
	"context"
	"fmt"
	"strconv"
	"time"

	"github.com/redis/go-redis/v9"

	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/services/monitor/onlineuser"
)

const (
	onlineUserKeyPrefix = "online_user:"
	invalidTokenKey     = "invalid_tokens:"
)

type redisStore struct {
	client *redis.Client
	logger log.Logger
}

func NewRedisStore(redis *redis.Client, logger log.Logger) *redisStore {
	return &redisStore{
		client: redis,
		logger: logger,
	}
}

func (r redisStore) Get(ctx context.Context, token string) (*onlineuser.OnlineCommand, error) {
	key := onlineUserKeyPrefix + token
	result, err := r.client.HGetAll(ctx, key).Result()
	if err != nil {
		return nil, err
	}
	online := &onlineuser.OnlineCommand{
		UserId:   result["id"],
		UserName: result["userName"],
		NickName: result["nickName"],
		Token:    result["token"],
		Ip:       result["ip"],
		Browser:  result["browser"],
		Os:       result["os"],
		Location: result["location"],
	}
	if t, e := strconv.ParseInt(result["loginTime"], 10, 64); e == nil {
		//日期格式化
		online.LoginTime = time.Unix(t, 0).Format("2006-01-02 15:04:05")
	}
	if t, e := strconv.ParseInt(result["lastActiveAt"], 10, 64); e == nil {
		online.LastActiveAt = time.Unix(t, 0).Format("2006-01-02 15:04:05")
	}
	return online, nil
}

// Set 保存在线用户信息
func (r redisStore) Set(ctx context.Context, cmd onlineuser.OnlineCommand, timeout int64) error {
	key := onlineUserKeyPrefix + cmd.Token
	// 设置过期时间
	expireTime := time.Duration(timeout) * time.Second // 设置过期时间
	if err := r.client.HSet(ctx, key,
		map[string]any{
			"userName":     cmd.UserName,
			"nickName":     cmd.NickName,
			"ip":           cmd.Ip,
			"browser":      cmd.Browser,
			"os":           cmd.Os,
			"location":     cmd.Location,
			"loginTime":    time.Now(),
			"lastActiveAt": time.Now(),
			"token":        cmd.Token,
			"userId":       cmd.UserId,
		}); err != nil {
		return fmt.Errorf("failed to save user to redis hash: %w", err)
	}

	// 设置过期时间
	if err := r.client.Expire(ctx, key, expireTime); err != nil {
		return fmt.Errorf("failed to set expire time: %w", err)
	}
	return nil
}

func (r redisStore) Remove(ctx context.Context, token string) error {
	key := onlineUserKeyPrefix + token
	_, err := r.client.Del(ctx, key).Result()
	if err != nil {
		return err
	}
	// 将 JWT 加入黑名单，设置过期时间为原 JWT 的过期时间（需从 token 解析）
	// 这里简化：统一设置 24 小时后过期（或根据业务设置）
	return r.client.Set(ctx, invalidTokenKey+token, "", 24*time.Hour).Err()
}

// IsSessionValid  检查会话是否有效
func (r redisStore) IsSessionValid(ctx context.Context, token string) (bool, error) {
	// 检查会话是否在失效名单中
	exists, err := r.client.Exists(ctx, invalidTokenKey+token).Result()
	if err != nil {
		return false, err
	}
	if exists > 0 {
		return false, nil
	}
	// 检查会话是否在在线用户列表中
	key := onlineUserKeyPrefix + token
	exists, err = r.client.Exists(ctx, key).Result()
	if err != nil {
		return false, err
	}
	if exists == 0 {
		return false, nil
	}
	// 更新最后活跃时间
	//_,err = r.client.HSet(ctx, key, "lastActiveAt", time.Now().Unix()).Result()
	//if err != nil {
	//	return false, err
	//}
	return true, nil
}
